package com.sparrow.common.attr.domain;

import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * 属性类，存储 IAttrType -> long
 * 使用 EnumMap 提高性能，避免装箱
 */
public class Attr {

    public static final Attr EMPTY = new Attr();

    private final Map<IAttrType, Long> values;

    public Attr() {
        this.values = new HashMap<>();
    }

    public static Attr of(Map<? extends IAttrType, Integer> attrMap) {
        Attr attr = new Attr();
        for (Map.Entry<? extends IAttrType, Integer> e : attrMap.entrySet()) {
            attr.set(e.getKey(), (long)e.getValue());
        }
        return attr;
    }

    public void add(IAttrType key, long value) {
        long old = values.getOrDefault(key, 0L);
        values.put(key, old + value);
    }


    public void set(IAttrType key, long value) {
        if (value == 0) {
            values.remove(key);
        } else {
            values.put(key, value);
        }
    }

    public long get(IAttrType key) {
        return values.getOrDefault(key, 0L);
    }

    /**
     * 属性加法
     */
    public void add(Attr other) {
        other.values.forEach((k, v) ->
                values.merge(k, v, Long::sum)
        );
    }

    /**
     * 属性减法
     */
    public void subtract(Attr other) {
        other.values.forEach((k, v) ->
                values.merge(k, -v, Long::sum)
        );
    }

    /**
     * 复制属性
     */
    public Attr copy() {
        Attr copy = new Attr();
        copy.values.putAll(this.values);
        return copy;
    }

    /**
     * 判断是否为空
     */
    public boolean isEmpty() {
        return values.isEmpty() || values.values().stream().allMatch(v -> v == 0L);
    }

    @Override
    public String toString() {
        return values.toString();
    }

    /**
     * 遍历属性
     */
    public void walkValue(BiConsumer<IAttrType, Long> consumer) {
        values.forEach(consumer);
    }

    /**
     * 快捷创建
     */
    public static Attr of(Object... keyValues) {
        if (keyValues.length % 2 != 0) {
            throw new IllegalArgumentException("参数必须成对出现: key1, value1, key2, value2...");
        }
        Attr attr = new Attr();
        for (int i = 0; i < keyValues.length; i += 2) {
            IAttrType key = (IAttrType) keyValues[i];
            long value = (Long) keyValues[i + 1];
            attr.set(key, value);
        }
        return attr;
    }

    public Map<Integer, Long> toMap() {
        Map<Integer, Long> map = new HashMap<>();
        for (Map.Entry<IAttrType, Long> e : values.entrySet()) {
            map.put(e.getKey().getType(), e.getValue());
        }
        return map;
    }
}
